home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 November: Tool Chest / Dev.CD Nov 00 TC Disk 1.toast / Sample Code / Devices and Hardware / Display Manager / DMFkey Source / RequestVideo.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-09-28  |  26.0 KB  |  700 lines  |  [TEXT/CWIE]

  1. /*
  2.     File:        RequestVideo.c
  3.     
  4.     Description:RequestVideo demonstrates the usage of the Display Manager
  5.                 introduced    with the PowerMacs and integrated into the system
  6.                 under System 7.5. With    the RequestVideo sample code library, 
  7.                 developers will be able to explore the Display Manager API by
  8.                 changing bit depth and screen resolution on    multisync displays
  9.                 on built-in, NuBus, and PCI based video. Display Manager 1.0
  10.                 is built into the Systems included with the first PowerMacs up
  11.                 through System 7.5.    Display Manager 2.0 is included with the 
  12.                 release of the new PCI based PowerMacs, and will be included
  13.                 in post 7.5 System Software releases. 
  14.                     
  15.                 It is a good idea to reset the screen(s) to the original setting 
  16.                 before exit since the call to RVSetVideoAsScreenPrefs() may not
  17.                 do the right thing under Display Manager 1.0 with certain video 
  18.                 drivers.
  19.     
  20.                 For information on the use of this sample code, please the 
  21.                 documentation in the Read Me file
  22.  
  23.  
  24.     Author:        EWA
  25.  
  26.     Copyright:     Copyright: © 1995-1999 by Apple Computer, Inc.
  27.                 all rights reserved.
  28.     
  29.     Disclaimer:    You may incorporate this sample code into your applications without
  30.                 restriction, though the sample code has been provided "AS IS" and the
  31.                 responsibility for its operation is 100% yours.  However, what you are
  32.                 not permitted to do is to redistribute the source as "DSC Sample Code"
  33.                 after having made changes. If you're going to re-distribute the source,
  34.                 we require that you make it clear in the source that the code was
  35.                 descended from Apple Sample Code, but that you've made changes.
  36.     
  37.     Change History (most recent first):
  38.                 6/24/99    Updated for Metrowerks Codewarror Pro 2.1(KG)
  39.                 5/31/95    Added RVGetCurrentVideoSetting and RVConfirmVideoRequest routines
  40.                         to make it easy to revert back to where you came from and to give
  41.                         the user a chance to confirm the new setting if the new mode was
  42.                         valid (ie: the card supports it) but not safe (the monitor may not).
  43.                         (EWA)
  44.                 5/24/95    Give the kAllValidModesBit requestFlags option for safe only or all
  45.                         valid resolution timings.(EWA)
  46.  
  47. */
  48. #include "RequestVideo.h"
  49.  
  50. // Internal includes
  51. #include <Dialogs.h>
  52. #include <ROMDefs.h>
  53. #include <Devices.h>
  54. #include <Errors.h>
  55. #include <Gestalt.h>
  56. #include <Memory.h>
  57. #include <Palettes.h>
  58. #include <Slots.h>
  59. #include <StdIO.h>
  60. #include <Displays.h>
  61.  
  62. #include <stdlib.h>
  63.  
  64. //--------------------------------------------------------------
  65. //
  66. // Internal defines, structs, typedefs, and routine declarations
  67. //
  68. //--------------------------------------------------------------
  69. #define        KMonoDev            0                        // false (handy definitions for gdDevType settings)
  70. #define        kColorDev            1                        // true
  71. #define        char_Enter            0x03                    // for our filter proc
  72. #define        char_Return            0x0D                    //
  73. #define        iRevertItem            1                        // User buttons
  74. #define        iConfirmItem        2                        //
  75. #define        kSecondsToConfirm    8                        // seconds before confirm dialog is taken down
  76. #define        rConfirmSwtchAlrt    2735                    // ID of alert dialog
  77.  
  78. struct DepthInfo {
  79.     VDSwitchInfoRec            depthSwitchInfo;            // This is the switch mode to choose this timing/depth
  80.     VPBlock                    depthVPBlock;                // VPBlock (including size, depth and format)
  81. };
  82. typedef struct DepthInfo DepthInfo;
  83.  
  84. struct ListIteratorDataRec {
  85.     VDTimingInfoRec            displayModeTimingInfo;        // Contains timing flags and such
  86.     unsigned long            depthBlockCount;            // How many depths available for a particular timing
  87.     DepthInfo                *depthBlocks;                // Array of DepthInfo
  88. };
  89. typedef struct ListIteratorDataRec ListIteratorDataRec;
  90.  
  91. void GetRequestTheDM1Way (        VideoRequestRecPtr requestRecPtr,
  92.                                 GDHandle walkDevice);
  93.  
  94. void GetRequestTheDM2Way (        VideoRequestRecPtr requestRecPtr,
  95.                                 GDHandle walkDevice,
  96.                                 DMDisplayModeListIteratorUPP myModeIteratorProc,
  97.                                 DMListIndexType theDisplayModeCount,
  98.                                 DMListType *theDisplayModeList);
  99.  
  100. pascal void ModeListIterator (    void *userData,
  101.                                 DMListIndexType itemIndex,
  102.                                 DMDisplayModeListEntryPtr displaymodeInfo);
  103.  
  104. Boolean FindBestMatch (            VideoRequestRecPtr requestRecPtr,
  105.                                 short bitDepth,
  106.                                 unsigned long horizontal,
  107.                                 unsigned long vertical);
  108.  
  109. void GravitateMonitors (void);
  110.  
  111. pascal Boolean ConfirmAlertFilter (DialogPtr dlg, EventRecord *evt, short *itemHit);
  112.  
  113. //--------------------------------------------------------------
  114. //
  115. // Implementation of sample code
  116. //
  117. //--------------------------------------------------------------
  118. OSErr RVSetVideoRequest (VideoRequestRecPtr requestRecPtr)
  119. {
  120.     GDHandle        aMonitor;
  121.     Boolean            displayMgrPresent;
  122.     unsigned long    displayMgrVersion;
  123.     OSErr            err;
  124.     Boolean            isColor;
  125.     long            value = 0;
  126.  
  127.     Gestalt(gestaltDisplayMgrVers, (long*)&displayMgrVersion);
  128.     Gestalt(gestaltDisplayMgrAttr,&value);
  129.     displayMgrPresent=value&(1<<gestaltDisplayMgrPresent);
  130.     if (displayMgrPresent)
  131.     {
  132.         if (requestRecPtr->displayMode && requestRecPtr->depthMode)
  133.         {
  134.             if (requestRecPtr->availBitDepth == 1)    // Based on avail bit depth, 
  135.                 isColor = KMonoDev;                    // set the device to a mono device, or
  136.             else isColor = kColorDev;                // set the device to a color device
  137.             SetDeviceAttribute(requestRecPtr->screenDevice,gdDevType,isColor);        
  138.             
  139.             // see how many monitors we have, aMonitor will be nil if we have only one.
  140.             aMonitor = DMGetFirstScreenDevice (dmOnlyActiveDisplays);            // get the first guy
  141.             aMonitor = DMGetNextScreenDevice ( aMonitor, dmOnlyActiveDisplays );    // get the next guy
  142.             
  143.             if (nil == aMonitor || displayMgrVersion >= 0x00020000)
  144.             {
  145.                 // only call DMSetDisplayMode if we have one monitor or DM2.0 is installed
  146.                 // since DM1.0 does not automatically gravitate monitors and our gravitate code
  147.                 // is not implemented.
  148.                 err = DMSetDisplayMode(    requestRecPtr->screenDevice,    // GDevice
  149.                         requestRecPtr->displayMode,                        // DM1.0 uses this
  150.                         &requestRecPtr->depthMode,                        // DM1.0 uses this
  151.                         (unsigned long) &(requestRecPtr->switchInfo),    // DM2.0 uses this rather than displayMode/depthMode combo
  152.                         nil);
  153.                 if (noErr == err)
  154.                 {
  155.                     // Do the monitor gravitate here if we are using a version less than DM2.0
  156.                     if (displayMgrVersion < 0x00020000)
  157.                         GravitateMonitors ();
  158.                 }
  159.                 else if (kDMDriverNotDisplayMgrAwareErr == err)
  160.                 {
  161.                     // DM not supported by driver, so all we can do is set the bit depth
  162.                     err = SetDepth (requestRecPtr->screenDevice, requestRecPtr->depthMode, gdDevType, isColor);
  163.                 }
  164.             }
  165.             else
  166.             {
  167.                 // we have more than one monitor and DM1.0 is installed, so all we can do is set the bit depth
  168.                 err = SetDepth (requestRecPtr->screenDevice, requestRecPtr->depthMode, gdDevType, isColor);
  169.             }
  170.             
  171.             return (err);    // we did try to set the request
  172.         }
  173.     }
  174.     return (-1);    // return a generic error
  175. }
  176.  
  177. // This extern should be removed once this function is formally defined in Displays.h
  178. extern pascal OSErr DMUseScreenPrefs(Boolean usePrefs, Handle displayState)
  179.  THREEWORDINLINE(0x303C, 0x03EC, 0xABEB);
  180.  
  181. OSErr RVSetVideoAsScreenPrefs (void)
  182. {
  183.     Handle        displaystate;
  184.     Boolean        displayMgrPresent;
  185.     long        value = 0;
  186.  
  187.     Gestalt(gestaltDisplayMgrAttr,&value);
  188.     displayMgrPresent=value&(1<<gestaltDisplayMgrPresent);
  189.     if (displayMgrPresent)
  190.     {
  191.         DMBeginConfigureDisplays (&displaystate);    // Tell the world it is about to change
  192.         DMUseScreenPrefs (true, displaystate);        // Make the change
  193.         DMEndConfigureDisplays (displaystate);        // Tell the world the change is over
  194.         
  195.         return (noErr);    // we (maybe) set the world back to a known setting
  196.     }
  197.     return (-1);    // return a generic error
  198. }
  199.  
  200. OSErr RVGetCurrentVideoSetting (VideoRequestRecPtr requestRecPtr)
  201. {
  202.     unsigned long        displayMgrVersion;
  203.     OSErr                error = paramErr;
  204.     CntrlParam            pBlock;
  205.     VDSwitchInfoRec        switchInfo;
  206.     AuxDCEHandle        theDCE;
  207.     VDSwitchInfoRec        videoMode;        
  208.  
  209.     requestRecPtr->availBitDepth            = 0;    // init to default - you can do it if it is important to you
  210.     requestRecPtr->availHorizontal            = 0;
  211.     requestRecPtr->availVertical            = 0;
  212.     requestRecPtr->availFlags                = 0;
  213.     requestRecPtr->displayMode                = -1; 
  214.     requestRecPtr->depthMode                = -1;
  215.     requestRecPtr->switchInfo.csMode        = 0;
  216.     requestRecPtr->switchInfo.csData        = 0;
  217.     requestRecPtr->switchInfo.csPage        = 0;
  218.     requestRecPtr->switchInfo.csBaseAddr    = 0;
  219.     requestRecPtr->switchInfo.csReserved    = 0;
  220.     
  221.     Gestalt(gestaltDisplayMgrVers, (long*)&displayMgrVersion);
  222.     if (requestRecPtr->screenDevice)
  223.     {
  224.         if (displayMgrVersion >= 0x00020000)
  225.         {    // get the info the DM 2.0 way
  226.             error = DMGetDisplayMode(requestRecPtr->screenDevice, &switchInfo);
  227.             if (noErr == error)
  228.             {
  229.                 requestRecPtr->depthMode            = switchInfo.csMode;
  230.                 requestRecPtr->displayMode            = switchInfo.csData; 
  231.                 requestRecPtr->switchInfo.csMode    = switchInfo.csMode;
  232.                 requestRecPtr->switchInfo.csData    = switchInfo.csData;
  233.             }
  234.             return (error);    // we (maybe) set the world back to a known setting
  235.         }
  236.         else
  237.         {    // get the info the DM 1.0 way
  238.             videoMode.csMode = -1;        // init to bogus value
  239.             videoMode.csData = -1;        // init to bogus value            
  240.             pBlock.ioNamePtr = nil;
  241.             pBlock.ioCRefNum = (*(requestRecPtr->screenDevice))->gdRefNum;
  242.             pBlock.csCode = cscGetCurMode;
  243.             *(Ptr *)&pBlock.csParam[0] = (Ptr)&videoMode;
  244.                 
  245.             error = PBStatusSync((ParmBlkPtr )&pBlock);    // ask the driver first....since we trust it the most
  246.                 
  247.             if ( noErr == error && ((-1 == videoMode.csMode) || (-1 == videoMode.csData)) )
  248.                 error = statusErr;
  249.             
  250.             if (noErr != error)    // if the driver has no clue fill it videoMode by hand as a last resort
  251.             {    
  252.                 theDCE = (AuxDCEHandle)GetDCtlEntry((*(requestRecPtr->screenDevice))->gdRefNum);
  253.                 
  254.                 if( theDCE )
  255.                 {
  256.                     videoMode.csData = (unsigned char)(*theDCE)->dCtlSlotId; 
  257.                     videoMode.csMode = (*(requestRecPtr->screenDevice))->gdMode;
  258.                     error = noErr;
  259.                 }
  260.             }
  261.             if (noErr == error)    // Set our data
  262.             {
  263.                 requestRecPtr->displayMode            = videoMode.csData; 
  264.                 requestRecPtr->depthMode            = videoMode.csMode;
  265.                 requestRecPtr->switchInfo.csMode    = videoMode.csMode;
  266.                 requestRecPtr->switchInfo.csData    = videoMode.csData;
  267.             }
  268.             return (error);    // we (maybe) set the world back to a known setting
  269.         }
  270.     }
  271.     return (-1);
  272. }
  273.  
  274. pascal Boolean ConfirmAlertFilter(DialogPtr theDialog, EventRecord *theEvent, short *itemHit)
  275. {
  276.     char charCode;
  277.     Boolean enterORreturn;
  278.     Boolean returnValue = false;
  279.  
  280.     if (0 == GetWRefCon(theDialog))
  281.         SetWRefCon (theDialog,TickCount());
  282.     else
  283.     {
  284.         if (GetWRefCon(theDialog) + kSecondsToConfirm * 60 < TickCount())
  285.         {
  286.             returnValue = true;
  287.             theEvent->what = nullEvent;
  288.             *itemHit = 1;
  289.         }
  290.         else
  291.         {
  292.             if (theEvent->what == keyDown)
  293.             {
  294.                 charCode = (char)theEvent->message & charCodeMask;
  295.                 enterORreturn = (charCode == (char)char_Return) || (charCode == (char)char_Enter);
  296.                 if (enterORreturn)
  297.                 {
  298.                     theEvent->what = nullEvent;
  299.                     returnValue = true;
  300.                     *itemHit = iRevertItem;
  301.                     if (enterORreturn && (0 != (theEvent->modifiers & optionKey)))
  302.                     {
  303.                         *itemHit = iConfirmItem;
  304.                     }
  305.                 }
  306.             }
  307.         }
  308.     }
  309.     return (returnValue);
  310. }
  311.  
  312. OSErr RVConfirmVideoRequest (VideoRequestRecPtr requestRecPtr)
  313. {
  314.     short            alertReturn;        // Alert() return value
  315.     ModalFilterUPP    confirmFilterUPP;    // got to have us one of them new fangled UPP thingies
  316.     
  317.     if (requestRecPtr->availFlags & 1<<kModeValidNotSafeBit)
  318.     {    // new mode is valid but not safe, so ask user to confirm
  319.         SetCursor(&qd.arrow);                                        // have to show the arrow
  320.  
  321.         confirmFilterUPP = NewModalFilterProc (ConfirmAlertFilter);    // create a new modal filter proc UPP
  322.         alertReturn = Alert(rConfirmSwtchAlrt, confirmFilterUPP);    // alert the user
  323.         DisposeRoutineDescriptor (confirmFilterUPP);                // of course there is no DisposeModalFilterProc...
  324.         
  325.         if (alertReturn != iConfirmItem)
  326.             return (-1);                            // tell the caller to switch back to a known setting
  327.         else return (noErr);                        // all is well with the new setting, just leave it
  328.     }
  329.     return (noErr);                                    // the mode was safe, so do nothing
  330. }
  331.  
  332.  
  333. OSErr RVRequestVideoSetting (VideoRequestRecPtr requestRecPtr)
  334. {
  335.     Boolean                            displayMgrPresent;
  336.     short                            iCount = 0;                    // just a counter of GDevices we have seen
  337.     DMDisplayModeListIteratorUPP    myModeIteratorProc = nil;    // for DM2.0 searches
  338.     SpBlock                            spBlock;
  339.     Boolean                            suppliedGDevice;    
  340.     DisplayIDType                    theDisplayID;                // for DM2.0 searches
  341.     DMListIndexType                    theDisplayModeCount;        // for DM2.0 searches
  342.     DMListType                        theDisplayModeList;            // for DM2.0 searches
  343.     long                            value = 0;
  344.     GDHandle                        walkDevice = nil;            // for everybody
  345.  
  346.     Gestalt(gestaltDisplayMgrAttr,&value);
  347.     displayMgrPresent=value&(1<<gestaltDisplayMgrPresent);
  348.     displayMgrPresent=displayMgrPresent && (SVersion(&spBlock)==noErr);    // need slot manager
  349.     if (displayMgrPresent)
  350.     {
  351.         // init the needed data before we start
  352.         if (requestRecPtr->screenDevice)                            // user wants a specifc device?
  353.         {
  354.             walkDevice = requestRecPtr->screenDevice;
  355.             suppliedGDevice = true;
  356.         }
  357.         else
  358.         {
  359.             walkDevice = DMGetFirstScreenDevice (dmOnlyActiveDisplays);            // for everybody
  360.             suppliedGDevice = false;
  361.         }
  362.         
  363.         myModeIteratorProc = NewDMDisplayModeListIteratorProc(ModeListIterator);    // for DM2.0 searches
  364.     
  365.         // Note that we are hosed if somebody changes the gdevice list behind our backs while we are iterating....
  366.         // ...now do the loop if we can start
  367.         if( walkDevice && myModeIteratorProc) do // start the search
  368.         {
  369.             iCount++;        // GDevice we are looking at (just a counter)
  370.             if( noErr == DMGetDisplayIDByGDevice( walkDevice, &theDisplayID, false ) )    // DM1.0 does not need this, but it fits in the loop
  371.             {
  372.                 theDisplayModeCount = 0;    // for DM2.0 searches
  373.                 if (noErr == DMNewDisplayModeList(theDisplayID, 0, 0, &theDisplayModeCount, &theDisplayModeList) )
  374.                 {
  375.                     // search NuBus & PCI the new kool way through Display Manager 2.0
  376.                     GetRequestTheDM2Way (requestRecPtr, walkDevice, myModeIteratorProc, theDisplayModeCount, &theDisplayModeList);
  377.                     DMDisposeList(theDisplayModeList);    // now toss the lists for this gdevice and go on to the next one
  378.                 }
  379.                 else
  380.                 {
  381.                     // search NuBus only the old disgusting way through the slot manager
  382.                     GetRequestTheDM1Way (requestRecPtr, walkDevice);
  383.                 }
  384.             }
  385.         } while ( !suppliedGDevice && nil != (walkDevice = DMGetNextScreenDevice ( walkDevice, dmOnlyActiveDisplays )) );    // go until no more gdevices
  386.         if( myModeIteratorProc )
  387.             DisposeRoutineDescriptor(myModeIteratorProc);
  388.         return (noErr);    // we were able to get the look for a match
  389.     }
  390.     return (-1);        // return a generic error
  391. }
  392.  
  393. void GetRequestTheDM1Way (VideoRequestRecPtr requestRecPtr, GDHandle walkDevice)
  394. {
  395.     AuxDCEHandle myAuxDCEHandle;
  396.     unsigned long    depthMode;
  397.     unsigned long    displayMode;
  398.     OSErr            error;
  399.     OSErr            errorEndOfTimings;
  400.     short            height;
  401.     short            jCount = 0;
  402.     Boolean            modeOk;
  403.     SpBlock            spAuxBlock;
  404.     SpBlock            spBlock;
  405.     unsigned long    switchFlags;
  406.     VPBlock            *vpData;
  407.     short            width;
  408.  
  409.     myAuxDCEHandle = (AuxDCEHandle) GetDCtlEntry((**walkDevice).gdRefNum);    
  410.     spBlock.spSlot = (**myAuxDCEHandle).dCtlSlot;
  411.     spBlock.spID = (**myAuxDCEHandle).dCtlSlotId;
  412.     spBlock.spExtDev = (**myAuxDCEHandle).dCtlExtDev;
  413.     spBlock.spHwDev = 0;                                // we are going to get this pup
  414.     spBlock.spParamData = 1<<foneslot;                    // this slot, enabled, and it better be here.
  415.     spBlock.spTBMask = 3;                                // don't have constants for this yet
  416.     errorEndOfTimings = SGetSRsrc(&spBlock);            // get the spDrvrHW so we know the ID of this puppy. This is important
  417.                                                         // since some video cards support more than one display, and the spDrvrHW
  418.                                                         // ID can, and will, be used to differentiate them.
  419.     
  420.     if ( noErr == errorEndOfTimings )
  421.     {
  422.         // reinit the param block for the SGetTypeSRsrc loop, keep the spDrvrHW we just got
  423.         spBlock.spID = 0;                                // start at zero, 
  424.         spBlock.spTBMask = 2;                            // 0b0010 - ignore DrvrSW - why ignore the SW side? Is it not important for video?
  425.         spBlock.spParamData = (1<<fall) + (1<<foneslot) + (1<<fnext);    // 0b0111 - this slot, enabled or disabled, so we even get 640x399 on Blackbird
  426.         spBlock.spCategory=catDisplay;
  427.         spBlock.spCType=typeVideo;
  428.         errorEndOfTimings = SGetTypeSRsrc(&spBlock);    // but only on 7.0 systems, not a problem since we require DM1.0
  429.         
  430.         // now, loop through all the timings for this GDevice
  431.         if ( noErr == errorEndOfTimings ) do
  432.         {
  433.             // now, loop through all possible depth modes for this timing mode
  434.             displayMode = (unsigned char)spBlock.spID;    // "timing mode, ie:resource ref number"
  435.             for (jCount = firstVidMode; jCount<= sixthVidMode; jCount++)
  436.             {
  437.                 depthMode = jCount;        // vid mode
  438.                 error = DMCheckDisplayMode(walkDevice,displayMode,depthMode,&switchFlags,0,&modeOk);
  439.     
  440.                 // only if the mode is safe or we override it with the kAllValidModesBit request flag
  441.                 if (    noErr == error &&
  442.                         modeOk &&
  443.                         (    switchFlags & 1<<kNoSwitchConfirmBit ||
  444.                             requestRecPtr->requestFlags & 1<<kAllValidModesBit
  445.                         )
  446.                     )
  447.                 {
  448.                     // have a good displayMode/depthMode combo - now lets look inside
  449.                     spAuxBlock = spBlock;                // don't ruin the iteration spBlock!!
  450.                     spAuxBlock.spID = depthMode;        // vid mode
  451.                     error=SFindStruct(&spAuxBlock);        // get back a new spsPointer
  452.                     if (noErr == error)                    // keep going if no error…
  453.                     {
  454.                         spAuxBlock.spID = 0x01;            // mVidParams request
  455.                         error=SGetBlock (&spAuxBlock);    // use the new spPointer and get back...a NewPtr'ed spResult
  456.                         if (noErr == error)                // …keep going if no error…
  457.                         {                                // We have data! lets have a look
  458.                             vpData = (VPBlock*)spAuxBlock.spResult;
  459.                             height = vpData->vpBounds.bottom;    // left and top are usually zero
  460.                             width = vpData->vpBounds.right;
  461.                             
  462.                             if (FindBestMatch (requestRecPtr, vpData->vpPixelSize, vpData->vpBounds.right, vpData->vpBounds.bottom))
  463.                             {
  464.                                 requestRecPtr->screenDevice = walkDevice;
  465.                                 requestRecPtr->availBitDepth = vpData->vpPixelSize;
  466.                                 requestRecPtr->availHorizontal = vpData->vpBounds.right;
  467.                                 requestRecPtr->availVertical = vpData->vpBounds.bottom;
  468.                                 requestRecPtr->displayMode = displayMode;
  469.                                 requestRecPtr->depthMode = depthMode;
  470.                                 requestRecPtr->switchInfo.csMode = depthMode;                // fill in for completeness
  471.                                 requestRecPtr->switchInfo.csData = displayMode;
  472.                                 requestRecPtr->switchInfo.csPage = 0;
  473.                                 requestRecPtr->switchInfo.csBaseAddr = 0;
  474.                                 requestRecPtr->switchInfo.csReserved = 0;
  475.                                 if (switchFlags & 1<<kNoSwitchConfirmBit)
  476.                                     requestRecPtr->availFlags = 0;                            // mode safe
  477.                                 else requestRecPtr->availFlags = 1<<kModeValidNotSafeBit;    // mode valid but not safe, requires user validation of mode switch
  478.                             }
  479.  
  480.                             if (spAuxBlock.spResult) DisposePtr ((Ptr)spAuxBlock.spResult);    // toss this puppy when done
  481.                         }
  482.                     }
  483.                 }
  484.             }
  485.             // go around again, looking for timing modes for this GDevice
  486.             spBlock.spTBMask = 2;        // ignore DrvrSW
  487.             spBlock.spParamData =  (1<<fall) + (1<<foneslot) + (1<<fnext);    // next resource, this slot, whether enabled or disabled
  488.             errorEndOfTimings = SGetTypeSRsrc(&spBlock);    // and get the next timing mode
  489.         } while ( noErr == errorEndOfTimings );    // until the end of this GDevice
  490.     }
  491.  
  492. }
  493.  
  494. pascal void ModeListIterator(void *userData, DMListIndexType, DMDisplayModeListEntryPtr displaymodeInfo)
  495. {
  496.     unsigned long            depthCount;
  497.     short                    iCount;
  498.     ListIteratorDataRec        *myIterateData        = (ListIteratorDataRec*) userData;
  499.     DepthInfo                *myDepthInfo;
  500.     
  501.     // set user data in a round about way
  502.     myIterateData->displayModeTimingInfo        = *displaymodeInfo->displayModeTimingInfo;
  503.     
  504.     // now get the DMDepthInfo info into memory we own
  505.     depthCount = displaymodeInfo->displayModeDepthBlockInfo->depthBlockCount;
  506.     myDepthInfo = (DepthInfo*)NewPtrClear(depthCount * sizeof(DepthInfo));
  507.  
  508.     // set the info for the caller
  509.     myIterateData->depthBlockCount = depthCount;
  510.     myIterateData->depthBlocks = myDepthInfo;
  511.  
  512.     // and fill out all the entries
  513.     if (depthCount) for (iCount=0; iCount < depthCount; iCount++)
  514.     {
  515.         myDepthInfo[iCount].depthSwitchInfo = 
  516.             *displaymodeInfo->displayModeDepthBlockInfo->depthVPBlock[iCount].depthSwitchInfo;
  517.         myDepthInfo[iCount].depthVPBlock = 
  518.             *displaymodeInfo->displayModeDepthBlockInfo->depthVPBlock[iCount].depthVPBlock;
  519.     }
  520. }
  521.  
  522. void GetRequestTheDM2Way (    VideoRequestRecPtr requestRecPtr,
  523.                             GDHandle walkDevice,
  524.                             DMDisplayModeListIteratorUPP myModeIteratorProc,
  525.                             DMListIndexType theDisplayModeCount,
  526.                             DMListType *theDisplayModeList)
  527. {
  528.     short                    jCount;
  529.     short                    kCount;
  530.     ListIteratorDataRec        searchData;
  531.  
  532.     searchData.depthBlocks = nil;
  533.     // get the mode lists for this GDevice
  534.     for (jCount=0; jCount<theDisplayModeCount; jCount++)        // get info on all the resolution timings
  535.     {
  536.         DMGetIndexedDisplayModeFromList(*theDisplayModeList, jCount, 0, myModeIteratorProc, &searchData);
  537.         
  538.         // for all the depths for this resolution timing (mode)...
  539.         if (searchData.depthBlockCount) for (kCount = 0; kCount < searchData.depthBlockCount; kCount++)
  540.         {
  541.             // only if the mode is valid and is safe or we override it with the kAllValidModesBit request flag
  542.             if    (    searchData.displayModeTimingInfo.csTimingFlags & 1<<kModeValid && 
  543.                     (    searchData.displayModeTimingInfo.csTimingFlags & 1<<kModeSafe ||
  544.                         requestRecPtr->requestFlags & 1<<kAllValidModesBit
  545.                     )
  546.                 )
  547.             {
  548.                 if (FindBestMatch (    requestRecPtr,
  549.                                     searchData.depthBlocks[kCount].depthVPBlock.vpPixelSize,
  550.                                     searchData.depthBlocks[kCount].depthVPBlock.vpBounds.right,
  551.                                     searchData.depthBlocks[kCount].depthVPBlock.vpBounds.bottom))
  552.                 {
  553.                     requestRecPtr->screenDevice = walkDevice;
  554.                     requestRecPtr->availBitDepth = searchData.depthBlocks[kCount].depthVPBlock.vpPixelSize;
  555.                     requestRecPtr->availHorizontal = searchData.depthBlocks[kCount].depthVPBlock.vpBounds.right;
  556.                     requestRecPtr->availVertical = searchData.depthBlocks[kCount].depthVPBlock.vpBounds.bottom;
  557.                     
  558.                     // now set the important info for DM to set the display
  559.                     requestRecPtr->depthMode = searchData.depthBlocks[kCount].depthSwitchInfo.csMode;
  560.                     requestRecPtr->displayMode = searchData.depthBlocks[kCount].depthSwitchInfo.csData;
  561.                     requestRecPtr->switchInfo = searchData.depthBlocks[kCount].depthSwitchInfo;
  562.                     if (searchData.displayModeTimingInfo.csTimingFlags & 1<<kModeSafe)
  563.                         requestRecPtr->availFlags = 0;                            // mode safe
  564.                     else requestRecPtr->availFlags = 1<<kModeValidNotSafeBit;    // mode valid but not safe, requires user validation of mode switch
  565.     
  566.                 }
  567.             }
  568.  
  569.         }
  570.     
  571.         if (searchData.depthBlocks)
  572.         {
  573.             DisposePtr ((Ptr)searchData.depthBlocks);    // toss for this timing mode of this gdevice
  574.             searchData.depthBlocks = nil;                // init it just so we know
  575.         }
  576.     }
  577. }
  578.  
  579. Boolean FindBestMatch (VideoRequestRecPtr requestRecPtr, short bitDepth, unsigned long horizontal, unsigned long vertical)
  580. {
  581.     // •• do the big comparison ••
  582.     // first time only if    (no mode yet) and
  583.     //                        (bounds are greater/equal or kMaximizeRes not set) and
  584.     //                        (depth is less/equal or kShallowDepth not set) and
  585.     //                        (request match or kAbsoluteRequest not set)
  586.     if    (    nil == requestRecPtr->displayMode
  587.             &&
  588.             (    (horizontal >= requestRecPtr->reqHorizontal &&
  589.                 vertical >= requestRecPtr->reqVertical)
  590.                 ||                                                        
  591.                 !(requestRecPtr->requestFlags & 1<<kMaximizeResBit)    
  592.             )
  593.             &&
  594.             (    bitDepth <= requestRecPtr->reqBitDepth ||    
  595.                 !(requestRecPtr->requestFlags & 1<<kShallowDepthBit)        
  596.             )
  597.             &&
  598.             (    (horizontal == requestRecPtr->reqHorizontal &&    
  599.                 vertical == requestRecPtr->reqVertical &&
  600.                 bitDepth == requestRecPtr->reqBitDepth)
  601.                 ||
  602.                 !(requestRecPtr->requestFlags & 1<<kAbsoluteRequestBit)    
  603.             )
  604.         )
  605.         {
  606.             // go ahead and set the new values
  607.             return (true);
  608.         }
  609.     else    // can we do better than last time?
  610.     {
  611.         // if    (kBitDepthPriority set and avail not equal req) and
  612.         //        ((depth is greater avail and depth is less/equal req) or kShallowDepth not set) and
  613.         //        (avail depth less reqested and new greater avail)
  614.         //        (request match or kAbsoluteRequest not set)
  615.         if    (    (    requestRecPtr->requestFlags & 1<<kBitDepthPriorityBit && 
  616.                     requestRecPtr->availBitDepth != requestRecPtr->reqBitDepth
  617.                 )
  618.                 &&
  619.                 (    (    bitDepth > requestRecPtr->availBitDepth &&
  620.                         bitDepth <= requestRecPtr->reqBitDepth
  621.                     )
  622.                     ||
  623.                     !(requestRecPtr->requestFlags & 1<<kShallowDepthBit)    
  624.                 )
  625.                 &&
  626.                 (    requestRecPtr->availBitDepth < requestRecPtr->reqBitDepth &&
  627.                     bitDepth > requestRecPtr->availBitDepth    
  628.                 )
  629.                 &&
  630.                 (    (horizontal == requestRecPtr->reqHorizontal &&    
  631.                     vertical == requestRecPtr->reqVertical &&
  632.                     bitDepth == requestRecPtr->reqBitDepth)
  633.                     ||
  634.                     !(requestRecPtr->requestFlags & 1<<kAbsoluteRequestBit)    
  635.                 )
  636.             )
  637.         {
  638.             // go ahead and set the new values
  639.             return (true);
  640.         }
  641.         else
  642.         {
  643.             // match resolution: minimize Δh & Δv
  644.             if    (    abs((requestRecPtr->reqHorizontal - horizontal)) <=
  645.                     abs((requestRecPtr->reqHorizontal - requestRecPtr->availHorizontal)) &&
  646.                     abs((requestRecPtr->reqVertical - vertical)) <=
  647.                     abs((requestRecPtr->reqVertical - requestRecPtr->availVertical))
  648.                 )
  649.             {
  650.                 // now we have a smaller or equal delta
  651.                 //    if (h or v greater/equal to request or kMaximizeRes not set) 
  652.                 if (    (horizontal >= requestRecPtr->reqHorizontal &&
  653.                         vertical >= requestRecPtr->reqVertical)
  654.                         ||
  655.                         !(requestRecPtr->requestFlags & 1<<kMaximizeResBit)
  656.                     )
  657.                 {
  658.                     // if    (depth is equal or kBitDepthPriority not set) and
  659.                     //        (depth is less/equal or kShallowDepth not set) and
  660.                     //        ([h or v not equal] or [avail depth less reqested and new greater avail] or depth equal avail) and
  661.                     //        (request match or kAbsoluteRequest not set)
  662.                     if    (    (    requestRecPtr->availBitDepth == bitDepth ||            
  663.                                 !(requestRecPtr->requestFlags & 1<<kBitDepthPriorityBit)
  664.                             )
  665.                             &&
  666.                             (    bitDepth <= requestRecPtr->reqBitDepth ||    
  667.                                 !(requestRecPtr->requestFlags & 1<<kShallowDepthBit)        
  668.                             )
  669.                             &&
  670.                             (    (requestRecPtr->availHorizontal != horizontal ||
  671.                                 requestRecPtr->availVertical != vertical)
  672.                                 ||
  673.                                 (requestRecPtr->availBitDepth < requestRecPtr->reqBitDepth &&
  674.                                 bitDepth > requestRecPtr->availBitDepth)
  675.                                 ||
  676.                                 (bitDepth == requestRecPtr->reqBitDepth)
  677.                             )
  678.                             &&
  679.                             (    (horizontal == requestRecPtr->reqHorizontal &&    
  680.                                 vertical == requestRecPtr->reqVertical &&
  681.                                 bitDepth == requestRecPtr->reqBitDepth)
  682.                                 ||
  683.                                 !(requestRecPtr->requestFlags & 1<<kAbsoluteRequestBit)    
  684.                             )
  685.                         )
  686.                     {
  687.                         // go ahead and set the new values
  688.                         return (true);
  689.                     }
  690.                 }
  691.             }
  692.         }
  693.     }
  694.     return (false);
  695. }
  696.  
  697. void GravitateMonitors (void)
  698. {
  699.     // do the magic gravitation here
  700. }